/*
 * lexeroperation.c
 *
 *  Created on: 2013-5-8
 *      Author: xkaying
 */

#include "lexer.h"
#include "lexerpackage.h"
#include "lexeroperation.h"
#include "lexercomment.h"

#include "../typedef/token.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

char *LexerOperation(char *ch, int *line, int *len, Lexer *plex, int size)
{
	assert(ch);
	assert(line);
	assert(len);
	assert(plex);
	int state;
	state = 0;
	Token *ptoken;
	ptoken = 0;
	while ((*len) < size) {
		switch (state)
		{
			case 0: {
				switch (*ch)
				{
					case '{': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_BlockStart);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case '}': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_BlockEnd);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case '[': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_IndexStart);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case ']': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_IndexEnd);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case ';': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_End);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case ':': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Extend);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case '(': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_BracketStart);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case ')': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_BracketEnd);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case '.': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Get);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case ',': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Comma);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case '=': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Equl);
						state = 12;
						ch++;
						(*len)++;
						continue;;
					}
					case '+': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Add);
						state = 1;
						ch++;
						(*len)++;
						continue;
					}
					case '-': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Sub);
						state = 2;
						ch++;
						(*len)++;
						continue;
					}
					case '*': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Mul);
						state = 3;
						ch++;
						(*len)++;
						continue;
					}
					case '/': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Div);
						state = 4;
						ch++;
						(*len)++;
						continue;
					}
					case '%': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Mod);
						state = 5;
						ch++;
						(*len)++;
						continue;
					}
						//位操作运算和比较符文
					case '|': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_BitOr);
						state = 6;
						ch++;
						(*len)++;
						continue;
					}
					case '&': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_BitAnd);
						state = 7;
						ch++;
						(*len)++;
						continue;
					}
					case '~': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_BitNot);
						LexerPush(plex, ptoken);
						ptoken = 0;
						ch++;
						(*len)++;
						return ch;
					}
					case '^': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_BitXor);
						state = 8;
						ch++;
						(*len)++;
						continue;
					}
					case '>': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_More);
						state = 9;
						ch++;
						(*len)++;
						continue;
					}
					case '<': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Less);
						state = 10;
						ch++;
						(*len)++;
						continue;
					}
					case '!': {
						if (ptoken) {
							printf("lexer operation错误,token已经存在.\n");
							return 0;
						}
						ptoken = TokenInit(TokenType_Not);
						state = 11;
						ch++;
						(*len)++;
						continue;
					}
					default:
						return ch;
				}
				printf("lexer operation状态机错误.\n");
				return 0;
			}
			case 1: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_EAdd;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				if ((*ch) == '+') {
					ptoken->type = TokenType_Inc;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 2: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_ESub;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				if ((*ch) == '-') {
					ptoken->type = TokenType_Dec;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 3: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_EMul;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}

				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 4: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_EDiv;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				if ((*ch) == '*') {
					free(ptoken);
					ptoken = 0;
					return LexerComment(ch, line, len, plex, size,
							CommentState_Block);
				}
				if ((*ch) == '/') {
					//注释
					free(ptoken);
					ptoken = 0;
					return LexerComment(ch, line, len, plex, size,
							CommentState_Line);
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 5: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_EMod;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 6: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_EBitOr;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				if ((*ch) == '|') {
					ptoken->type = TokenType_Or;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 7: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_EBitAnd;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				if ((*ch) == '&') {
					ptoken->type = TokenType_And;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 8: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_EBitXor;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 9: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_EMore;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				if ((*ch) == '>') {
					ptoken->type = TokenType_RightShift;
					state = 90;
					ch++;
					(*len)++;
					continue;;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 90: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_ERightShift;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 10: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_ELess;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				if ((*ch) == '<') {
					ptoken->type = TokenType_LeftShift;
					state = 100;
					ch++;
					(*len)++;
					continue;;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 100: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_ELeftShift;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 11: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_ENot;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			case 12: {
				if ((*ch) == '=') {
					ptoken->type = TokenType_EE;
					LexerPush(plex, ptoken);
					ptoken = 0;
					ch++;
					(*len)++;
					return ch;
				}
				LexerPush(plex, ptoken);
				ptoken = 0;
				return ch;
			}
			default: {
				printf("lexer operation状态机错误.\n");
				return 0;

			}

		}

	}
	if (ptoken != 0) {
		LexerPush(plex, ptoken);
		ptoken = 0;
	}
	return ch;
}
